package org.abettor.pushbox.view;

/**
 * 绘画地图的控件
 */
import org.abettor.pushbox.map.Boxmap;
import org.abettor.pushbox.map.Point;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;

public class MakeMapView extends ImageView {
	public static final int BOX_PRESSED = 1, WALL_PRESSED = 2,
			DEST_PRESSED = 3, CANCEL_PRESSED = 4, PERSON_PRESSED = 5,
			NULL_PRESSED = 0;
	public static final int MAX_ZOOM = 2;// 放大的最大倍数
	public static final float ZOOM_SCALE = 1.25F;
	private int status = NULL_PRESSED;// 箱子的状态
	private boolean hasModed = false;// 是否已经编辑过
	private boolean isDragging = false;// 用来判断地图是否在拖动状态中
	private final float EXT_X = 0, EXT_Y = 0;
	private final float BORDER = 5;
	private BoxMapImageDraw imageDraw;// 绘制图像的类
	private int width, height;// 地图的高度和宽度
	protected Boxmap map;// 需要绘制的地图
	private float[] mMatrixValues = new float[9];// 用来临时获得matrix的值的数组
	protected Bitmap mBoxMap;// 地图的背景
	protected Matrix mDisplayMatrix = new Matrix();// 显示图片时的matrix
	int mThisWidth = -1, mThisHeight = -1;// 当前绘制图片的宽度和高度

	public MakeMapView(Context context) {
		super(context);
		init(context);
	}

	public MakeMapView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 初始化控件
	private void init(Context context) {
		imageDraw = new BoxMapImageDraw(context);
		setScaleType(ImageView.ScaleType.MATRIX);
		mGestureDetector = new GestureDetector(context, new MyGestureListener());
	}

	@Override
	public void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		if (mBoxMap == null) {
			return;
		}
		super.setImageMatrix(this.mDisplayMatrix);
	}

	/**
	 * 产生绘制的地图
	 */
	public void generateBitmap() {
		if (mBoxMap != null) {
			mBoxMap.recycle();
		}
		float thewidth = imageDraw.getClipWidth() * this.width + EXT_X;
		float theheight = imageDraw.getClipHeight() * this.height + EXT_Y;
		mBoxMap = Bitmap.createBitmap((int) thewidth, (int) theheight,
				Bitmap.Config.RGB_565);
		drawGrid(mBoxMap);
		super.setImageBitmap(mBoxMap);
	}

	// 绘制坐标系
	private void drawGrid(Bitmap bitmap) {
		Canvas c1 = new Canvas(bitmap);
		Paint paint = new Paint();
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				if (map.isEmpty(x, y)) {
					imageDraw.drawBackGroudClip(c1, x, y, paint);
				} else {
					imageDraw.drawEveryClipWithOutBack(c1, x, y, map);
				}
			}
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		Paint paint = new Paint();
		paint.setColor(Color.BLUE);
		paint.setStrokeWidth(BORDER);
		Paint paint1 = new Paint();
		paint1.setColor(Color.RED);
		paint1.setStrokeWidth(BORDER);
		int w = super.getWidth();
		int h = super.getHeight();
		// 画边框的作用
		canvas.drawLine(w, 0, w, h, paint);
		float scale = getScale(this.mDisplayMatrix);
		if (mBoxMap != null) {
			int leny = caculateScrollLenthY();
			float tmpHeight = mBoxMap.getHeight() * scale;
			int movy = caculateMovY(tmpHeight, super.getHeight());
			canvas.drawLine(w, movy, w, movy + leny, paint1);
		}
		canvas.drawLine(0, h, w, h, paint);
		if (mBoxMap != null) {
			int lenx = caculateScrollLenthX();
			float tmpWidth = mBoxMap.getWidth() * scale;
			int movx = caculateMovX(tmpWidth, super.getWidth());
			canvas.drawLine(movx, h, movx + lenx, h, paint1);
		}
		canvas.drawLine(0, 0, 0, h, paint);
		canvas.drawLine(0, 0, w, 0, paint);
	}

	// 计算边框的长度
	private int caculateScrollLenthX() {
		float scale = getScale(this.mDisplayMatrix);
		float tmp = mBoxMap.getWidth() * scale;
		int w = super.getWidth();
		return caculateScrollLenth(tmp, w);
	}

	// 计算竖直边框的长度
	private int caculateScrollLenthY() {
		float scale = getScale(this.mDisplayMatrix);
		float tmp = mBoxMap.getHeight() * scale;
		int h = super.getHeight();
		return caculateScrollLenth(tmp, h);
	}

	// 计算横轴需要移动的距离
	private int caculateMovX(float width, float w) {
		float translatex = getTransX(this.mDisplayMatrix);
		return (int) ((-translatex) * (w / width));
	}

	// 计算纵轴需要移动的距离
	private int caculateMovY(float height, float h) {
		float translatey = getTransY(this.mDisplayMatrix);
		return (int) ((-translatey) * (h / height));
	}

	private float getTransX(Matrix matrix) {
		matrix.getValues(mMatrixValues);
		float translatex = mMatrixValues[Matrix.MTRANS_X];
		return translatex;
	}

	// 获得总位移
	private float getTransY(Matrix matrix) {
		matrix.getValues(mMatrixValues);
		float translatey = mMatrixValues[Matrix.MTRANS_Y];
		return translatey;
	}

	// 获得放大的倍数
	private float getScale(Matrix matrix) {
		matrix.getValues(mMatrixValues);
		float s = mMatrixValues[Matrix.MSCALE_X];
		return s;
	}

	private int caculateScrollLenth(float photowidth, float w) {
		if (photowidth <= w) {
			return 0;
		}
		return (int) (w * (w / photowidth));
	}

	// 增加手势的支持
	GestureDetector mGestureDetector = null;

	// 增加对手势的支持
	private class MyGestureListener extends
			GestureDetector.SimpleOnGestureListener {
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			float scale = getScale(MakeMapView.this.mDisplayMatrix);
			float deltax, deltay;
			Matrix tempMatrix = new Matrix(MakeMapView.this.mDisplayMatrix);
			tempMatrix.postTranslate(-distanceX, -distanceY);
			float transx = getTransX(tempMatrix);
			float transy = getTransY(tempMatrix);
			if (transx > 0) {
				deltax = 0;
			} else if (transx < -(MakeMapView.this.mBoxMap.getWidth()*scale - MakeMapView.this
					.getWidth())) {
				deltax = 0;
			} else {
				deltax = -distanceX;
			}
			if (transy > 0) {
				deltay = 0;
			} else if (transy < -(MakeMapView.this.mBoxMap.getHeight()*scale - MakeMapView.this
					.getHeight())) {
				deltay = 0;
			} else {
				deltay = -distanceY;
			}
			mDisplayMatrix.postTranslate(deltax, deltay);
			MakeMapView.this.setImageMatrix(mDisplayMatrix);
			return true;
		}
	}

	// 进行移位的操作
	protected void postTranslate(float dx, float dy) {
		this.mDisplayMatrix.postTranslate(dx, dy);
		super.setImageMatrix(mDisplayMatrix);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mGestureDetector.onTouchEvent(event)) {
			isDragging = true;
			return true;
		}
		if (event.getAction() == MotionEvent.ACTION_UP) {
			if (isDragging) {
				isDragging = false;
				return true;
			}
			float x = event.getX();
			float y = event.getY();
			int mapX = translateX2BoxmapX(x);
			int mapY = translateY2BoxmapY(y);
			putXY(mapX, mapY);
		}
		return super.onTouchEvent(event);
	}

	// 把相应坐标至为相应的状态
	private void putXY(int mapx, int mapy) {
		if(mapx > map.getWidth() -1){
			mapx = map.getWidth() -1;
		}
		if(mapx < 0){
			mapx = 0;
		}
		if(mapy > map.getHeight() - 1){
			mapy = map.getHeight() - 1;
		}
		if(mapy < 0){
			mapy = 0;
		}
		Point point = null;
		switch (status) {
		case BOX_PRESSED:
			hasModed = map.setBox(mapx, mapy);
			break;
		case WALL_PRESSED:
			hasModed = map.setBrick(mapx, mapy);
			break;
		case DEST_PRESSED:
			hasModed = map.setDest(mapx, mapy);
			break;
		case PERSON_PRESSED:
			point = map.getPerson();
			hasModed = map.setPerson(mapx, mapy);
			break;
		case CANCEL_PRESSED:
			if (map.isBox(mapx, mapy)) {
				hasModed = map.clearBox(mapx, mapy);
			} else if (map.isBrick(mapx, mapy)) {
				hasModed = map.clearBrick(mapx, mapy);
			} else if (map.isDest(mapx, mapy)) {
				hasModed = map.clearDest(mapx, mapy);
			} else if (map.isPerson(mapx, mapy)) {
				hasModed = map.clearPerson(mapx, mapy);
			}
			break;
		}
		// 进行画图的操作
		Canvas c1 = new Canvas(this.mBoxMap);
		imageDraw.drawEveryClipWithOutBack(c1, mapx, mapy, map);
		if (point != null) {
			imageDraw.drawEveryClipWithOutBack(c1, point.getX(), point.getY(),
					map);
		}
		super.setImageBitmap(mBoxMap);
	}

	// 进行放大的操作
	public void zoomIn() {
		zoom(ZOOM_SCALE);
	}
	//进行缩小的操作
	public void zoomOut(){
		zoom(1/ZOOM_SCALE);
	}
	public void zoom(float zoom){
		Matrix m = new Matrix(this.mDisplayMatrix);
		m.postScale(zoom, zoom);
		float scal = getScale(m);
		if (scal > MAX_ZOOM) {
			scal = MAX_ZOOM;
		} else if (scal < 1) {
			scal = 1;
		}
		this.mDisplayMatrix.setScale(scal, scal);
		super.setImageMatrix(mDisplayMatrix);
	}
	// 把物理坐标转化为数字坐标
	private int translateX2BoxmapX(float x) {
		float scale = getScale(mDisplayMatrix);
		float mov_x = getTransX(super.getImageMatrix());
		float distanceX = x - mov_x;
		return (int) (distanceX / (imageDraw.getClipWidth()*scale));
	}

	// 把物理坐标转化为地图坐标
	private int translateY2BoxmapY(float y) {
		float scale = getScale(mDisplayMatrix);
		float mov_y = getTransY(super.getImageMatrix());
		float distanceY = y - mov_y;
		return (int) (distanceY / (imageDraw.getClipHeight()*scale));
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public Boxmap getMap() {
		return map;
	}

	public void setMap(Boxmap map) {
		this.map = map;
		this.width = map.getWidth();
		this.height = map.getHeight();
	}

	/**
	 * 检查地图是否合法
	 * 
	 * @return
	 */
	public int checkMapIsValid() {
		return map.checkMapIsValid();
	}

	public boolean isHasModed() {
		return hasModed;
	}

	public void setHasModed(boolean hasModed) {
		this.hasModed = hasModed;
	}
}
